package com.btc.watcher;

import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.graphics.Color;
import android.widget.RemoteViews;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.ByteArrayBuffer;
import org.json.JSONArray;
import org.json.JSONObject;

// -------------------------------------------------------------------------
/**
 * Watches MtGox btc market 1st version: Feb 3, 2011
 *
 * @author Dest
 * @version March 3, 2011
 */
public class BitcoinWatcher
    extends Activity
{

    public static final String REFRESH                      =
                                                                "com.btc.watcher.REFRESH";

    /**
     * We store references to the various TextViews here Temporarily commented
     * out to increase speed
     */
    /*
     * TextView tv; TextView highText; TextView lowText; TextView volText;
     * TextView buyText; TextView sellText; TextView lastText;
     */
    TextView                   endText;

    // The results of the Mt Gox login
    private String             goxResults                   = null;
    private GoxAccount         goxAccount                   = null;

    // this stores the current order to place
    private GoxOrder           goxPlaceOrder                = null;
    /**
     * Menu options we display when launching
     */
    final CharSequence         iPriceGraph                  =
                                                                "Show Price Graph";
    final CharSequence         iAccount                     =
                                                                "My Mt.Gox Account";
    final CharSequence         iRefresh                     =
                                                                "Force Widget Refresh";

    final CharSequence         iPreferences                 = "Settings";
    final CharSequence         iClose                       = "Close";



    /**
     * Other constants
     */
    final int                  SCREEN_ORIENTATION_LANDSCAPE = 0;
    final Handler              mAccountHandler              = new Handler();
    final Handler              mOrderHandler              = new Handler();
    final Handler              mPlaceOrderHandler              = new Handler();
    final Handler              mGraphHandler              = new Handler();

    private GraphView g_graphView = null;

    private ProgressDialog orderProgressDialog;
    private ProgressDialog graphProgressDialog;
    private ProgressDialog placeOrderProgressDialog;

    // keeps track of current screen incase orientation changes

    private int currentView;
    private GraphView currentGraphView;
    private final int USE_GRAPH_VIEW = -1;
    private Stack<Integer> previousViews = new Stack<Integer>();

    //preferences
    String pref_Username = "";


    /**
     * saves the current view (so back button and rotation work)
     * then sets a new view
     */
    private void setMyView(int pView) {
        previousViews.push(currentView);
        currentView = pView;
        setContentView(pView);
    }

    /**
     * saves the current view (so back button and rotation work)
     * then sets a new view, specifically for GraphView
     */
    private void setMyView(GraphView pView) {
        previousViews.push(currentView);
        currentView = USE_GRAPH_VIEW;
        currentGraphView = g_graphView;
        setContentView(pView);
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setMyView(R.layout.main);

        // Temporarily commented out to increase speed
        /*
         * tv = (TextView)findViewById(R.id.displayText); highText =
         * (TextView)findViewById(R.id.highText); lowText =
         * (TextView)findViewById(R.id.lowText); volText =
         * (TextView)findViewById(R.id.volText); buyText =
         * (TextView)findViewById(R.id.buyText); sellText =
         * (TextView)findViewById(R.id.sellText); lastText =
         * (TextView)findViewById(R.id.lastText);
         */
        endText = (TextView)findViewById(R.id.endText);
        endText
            .setText("\nIMPORTANT: Be sure to use the Widget!\n On the "
                + "home screen, long press on an empty space, then select Android"
                + " Widgets, then select Bitcoin Alert!\n\nTips: Click on the "
                + "bitcoin in the widget to bring up this screen. The widget automatically"
                + " refreshes every 30 minutes; the update time is displayed in red if the "
                + "update was not successful, which is usally due to dropped 3G or Wifi signal."
                + " Press the 'menu' key on your Android device and select 'Force Widget Refresh'"
                + " to fix a failed update. \n\nAbout: Bitcoin Alert created by Dest Romano of "
                + "Philosophy apps. Graphs created by the GraphView library, written by Arno Den "
                + "Hond, modified by Dest Romano.");

        displayMenu();

    }

    @Override
    public void onStart() {
        super.onStart();
        readPreferences();
    }


    /**
     * displayMenu is called whenever the app is run or the menu key is pressed
     * inside the application.
     */
    private void displayMenu()
    {
        // [[1]]
        final CharSequence[] items =
            { iPriceGraph, iAccount, iRefresh, iPreferences, iClose };

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Select an option");
        builder.setItems(items, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int item)
            {
                if (items[item] == iPriceGraph)
                {
                    dialog.cancel();
                    viewGraph();
                }
                else if (items[item] == iAccount)
                {
                    dialog.cancel();
                    displayAccountPage();
                }
                else if (items[item] == iRefresh)
                {
                    dialog.cancel();
                    Intent intent =
                        new Intent(
                            getApplicationContext(),
                            WatcherWidgetProvider.class);
                    intent.setAction(REFRESH);
                    sendBroadcast(intent);
                    // updateStats();
                }
                else if(items[item] == iPreferences) {
                    dialog.cancel();
                    Intent settingsActivity = new Intent(getBaseContext(),
                        Preferences.class);
                    startActivity(settingsActivity);
                }
                else
                {
                    dialog.cancel();
                }
            }
        });

        /*
         * builder.setPositiveButton( "Show Price over last 48 Hours", new
         * DialogInterface.OnClickListener() { public void
         * onClick(DialogInterface dialog, int id) { dialog.cancel();
         * displayPreviousPriceGraph(); } }); builder.setNeutralButton(
         * "Force Update", new DialogInterface.OnClickListener() { public void
         * onClick(DialogInterface dialog, int id) { dialog.cancel(); Intent
         * intent = new Intent( getApplicationContext(),
         * WatcherWidgetProvider.class); intent.setAction(REFRESH);
         * sendBroadcast(intent); } }); builder.setNegativeButton( "Close", new
         * DialogInterface.OnClickListener() { public void
         * onClick(DialogInterface dialog, int id) { dialog.cancel(); } });
         */

        AlertDialog alert = builder.create();
        alert.show();
    }


    /**
     * in onPrepareOptionsMenu, we display our own custom menu and return false
     * as to void the default android menu
     *
     * @param menu
     *            we ignore this (for now)
     * @return boolean false to ignore the defualt menu, true to display it
     */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu)
    {
        displayMenu();

        return false; // so we don't display the actual menu
    }


    /**
     * in onCreateOptionsMenu, we display our own custom menu and return false
     * as to void the default android menu
     *
     * @param menu
     *            we ignore this (for now)
     * @return boolean false to ignore the defualt menu, true to display it
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        displayMenu();

        return false; // so we don't display the actual menu
    }


    /**
     * displayAccountPage displays the users Mt Gox Account -It connects to Mt
     * Gox and displays the account info Todo: Allow the user to remember login
     * name and pass -Store the goxAccount object between sessions
     */
    private void displayAccountPage()
    {
        // [[2]]
        setMyView(R.layout.account);
        Button goxLoginButton = (Button)findViewById(R.id.loginButton);

        if (goxAccount == null)
        {
            goxLoginButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v)
                {
                    goxLogin();
                }
            });
            if(pref_Username != "") {
                EditText goxName = (EditText)findViewById(R.id.nameText);
                goxName.setText(pref_Username, TextView.BufferType.EDITABLE);
            }
        }
        else
        {
            Button viewOrdersButton =
                (Button)findViewById(R.id.buttonViewOrders);
            Button buyButton = (Button)findViewById(R.id.buttonBuy);
            Button sellButton = (Button)findViewById(R.id.buttonSell);
            TextView accountDetails =
                (TextView)findViewById(R.id.goxAccountDetails);
            EditText goxName = (EditText)findViewById(R.id.nameText);
            EditText goxPass = (EditText)findViewById(R.id.passText);

            accountDetails.setText("Logged in as "
                + goxAccount.getAccountName() + "\nUSD: $"
                + goxAccount.getAccountUSD() + " \nBTC: "
                + goxAccount.getAccountBTC());
            goxLoginButton.setVisibility(View.GONE);
            goxName.setVisibility(View.GONE);
            goxPass.setVisibility(View.GONE);
            viewOrdersButton.setVisibility(View.VISIBLE);
            viewOrdersButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v)
                {
                    viewOrders();
                }
            });

            sellButton.setVisibility(View.VISIBLE);
            sellButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v)
                {
                    displaySellPage();
                }
            });

            buyButton.setVisibility(View.VISIBLE);
            buyButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v)
                {
                    displayBuyPage();
                }
            });
        }

    }

    /**
     * displayBuyPage displays a page with a usd and btc field, allowing
     * users to place orders to their account
     */
    private void displayBuyPage()
    {
        setMyView(R.layout.buypage);

        if (goxAccount == null)
        {
            displayAccountPage();
            return;
        }
        else
        {
            Button placeOrderButton =
                (Button)findViewById(R.id.placeOrderButton);

            TextView accountDetails =
                (TextView)findViewById(R.id.goxAccountDetails);

            accountDetails.setText("Logged in as "
                + goxAccount.getAccountName() + "\nUSD: $"
                + goxAccount.getAccountUSD() + " \nBTC: "
                + goxAccount.getAccountBTC());

            Button viewOrdersButton =
                (Button)findViewById(R.id.buttonViewOrders);
            viewOrdersButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v)
                {
                    viewOrders();
                }
            });

            placeOrderButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v)
                {
                    preparePlaceOrder(GoxOrder.TYPE_BUY);
                }
            });


        }

    }

    /**
     * displaySellPage displays a page with a usd and btc field, allowing
     * users to place orders to their account
     */
    private void displaySellPage()
    {

        setMyView(R.layout.sellpage);

        if (goxAccount == null)
        {
            displayAccountPage();
            return;
        }
        else
        {
            Button placeOrderButton =
                (Button)findViewById(R.id.placeOrderButton);

            TextView accountDetails =
                (TextView)findViewById(R.id.goxAccountDetails);

            accountDetails.setText("Logged in as "
                + goxAccount.getAccountName() + "\nUSD: $"
                + goxAccount.getAccountUSD() + " \nBTC: "
                + goxAccount.getAccountBTC());

            Button viewOrdersButton =
                (Button)findViewById(R.id.buttonViewOrders);
            viewOrdersButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v)
                {
                    viewOrders();
                }
            });

            placeOrderButton.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v)
                {
                    preparePlaceOrder(GoxOrder.TYPE_SELL);
                }
            });


        }

    }

    /**
     * goxLogin takes the user's name and password and tries to log into Mt Gox.
     * -Displays a popup if we can't connect or if the login info is wrong
     */
    private void preparePlaceOrder(int pOrderType)
    {
        EditText goxBTC = (EditText)findViewById(R.id.btcText);
        EditText goxUSD = (EditText)findViewById(R.id.usdText);


        Double BTC = 0.0;
        Double USD = 0.0;
        try {
            BTC = Double.parseDouble(goxBTC.getText().toString());
            USD= Double.parseDouble(goxUSD.getText().toString());
        } catch (Exception e) {
            createPopup ("Be sure to enter a number amount!");
            return;
        }

        if (BTC <= 0)
        {
            createPopup("The BTC amount of "+BTC+" is not valid.");
            return;
        }

        if (USD <= 0)
        {
            createPopup("The USD amount of "+USD+" is not valid.");
            return;
        }

        goxPlaceOrder = new GoxOrder();
        goxPlaceOrder.setOrderType(pOrderType);
        goxPlaceOrder.setBtcAmount(BTC);
        goxPlaceOrder.setOrderPrice(USD);

        requestPlaceOrder();

    }

    /**
     * mAccountLogin's run() is called when our AccountThread is finished
     * connecting to Mt Gox We should then have the goxResults and goxAccount
     * object if everything went ok
     */
    final Runnable mAccountLogin = new Runnable() {
         public void run()
         {
             if (goxResults != null)
             {

                 try
                 {
                     JSONObject jObject =
                         new JSONObject(goxResults);
                     if (jObject.has("error"))
                     {
                         createPopup("Error: "
                             + jObject
                                 .getString("error"));
                         return;
                     }
                     else if (jObject.has("usds")
                         && jObject.has("btcs")
                         && goxAccount != null)
                     {
                         String usd =
                             jObject
                                 .getString("usds");
                         String btcs =
                             jObject
                                 .getString("btcs");

                         goxAccount
                             .setAccountUSD(usd);
                         goxAccount
                             .setAccountBTC(btcs);

                         // lets redisplay the page
    // with updated info
                         displayAccountPage();

                     }
                     else
                         createPopup("There was an error accessing the account.");
                 }
                 catch (Exception e)
                 {
                     createPopup(goxResults);
                 }
             }
             else
             {
                 createPopup("Login was not successful.\nCheck your Wifi or 3G connection");
             }
         }
     };


    /**
     * goxLogin takes the user's name and password and tries to log into Mt Gox.
     * -Displays a popup if we can't connect or if the login info is wrong
     */
    private void goxLogin()
    {
        EditText goxName = (EditText)findViewById(R.id.nameText);
        EditText goxPass = (EditText)findViewById(R.id.passText);

        String accountName = goxName.getText().toString();
        String accountPass = goxPass.getText().toString();

        if (accountName.length() == 0 || accountPass.length() == 0)
        {
            createPopup("You must enter your Mt.Gox username and password.");
            return;
        }

        AccountThread at = new AccountThread(accountName, accountPass);
        at.start();
    }


    public class AccountThread
        extends Thread
    {
        String tAccountName;
        String tAccountPass;


        public AccountThread(String pName, String pPass)
        {
            tAccountName = pName;
            tAccountPass = pPass;
        }


        public void run()
        {
            goxResults = connectToGox(tAccountName, tAccountPass);
            goxAccount = new GoxAccount(tAccountName, tAccountPass);
            mAccountHandler.post(mAccountLogin);
        }

    }


    /**
     * connectToGox attempts to connect to MtGox with the specified name and
     * pass
     *
     * @param pName
     *            the account name
     * @param pPass
     *            the account pass
     * @return String the query results (null if the query failed)
     */
    private String connectToGox(String pName, String pPass)
    {

        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost("https://mtgox.com/code/getFunds.php");

        try
        {
            List<NameValuePair> nameValuePairs =
                new ArrayList<NameValuePair>(2);
            nameValuePairs.add(new BasicNameValuePair("name", pName));
            nameValuePairs.add(new BasicNameValuePair("pass", pPass));
            httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            HttpResponse response = httpclient.execute(httppost);

            InputStream is = response.getEntity().getContent();
            BufferedInputStream bis = new BufferedInputStream(is);
            ByteArrayBuffer baf = new ByteArrayBuffer(200);

            // convert byte array to string
            int current = 0;
            while ((current = bis.read()) != -1)
            {
                baf.append((byte)current);
            }

            String text = new String(baf.toByteArray());

            return text;
        }
        catch (Exception e)
        {
            return null;
        }

    }

    // [[5]]
    private void viewOrders() {
        if(orderProgressDialog != null && orderProgressDialog.isShowing()) {
            return;
        }
        orderProgressDialog = ProgressDialog.show(this, "Working..", "Retrieving orders", true, false);
        OrderThread ot = new OrderThread();
        ot.start();
    }

    public class OrderThread
        extends Thread
    {

        public void run()
        {
            retrieveOrders();
            mOrderHandler.post(mOrderView); //after retrieveOrders is done, do this
        }

    }


    /**
     * viewOrders attempts to connect to MtGox with the specified name and pass
     * and retrieve a list of orders
     */
    private void retrieveOrders()
    {
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost =
            new HttpPost("https://mtgox.com/code/getOrders.php");

        String pName = goxAccount.getAccountName();
        String pPass = goxAccount.getAccountPass();
        goxAccount.clearOrders();

        try
        {
            List<NameValuePair> nameValuePairs =
                new ArrayList<NameValuePair>(2);
            nameValuePairs.add(new BasicNameValuePair("name", pName));
            nameValuePairs.add(new BasicNameValuePair("pass", pPass));
            httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

            HttpResponse response = httpclient.execute(httppost);

            InputStream is = response.getEntity().getContent();
            BufferedInputStream bis = new BufferedInputStream(is);
            ByteArrayBuffer baf = new ByteArrayBuffer(200);

            // convert byte array to string
            int current = 0;
            while ((current = bis.read()) != -1)
            {
                baf.append((byte)current);
            }

            String text = new String(baf.toByteArray());

            //fix: cant create popup in thread
            //createPopup(text);

            JSONObject jParse = new JSONObject(text);

            JSONArray jArray = jParse.getJSONArray("orders");
            JSONObject jKey;

            if (jArray == null || jArray.length() <= 0) {
                 //fix: cant create popup in thread
                //createPopup("Could not access the account...");
                return;
            }

            String orderID;
            int orderType;
            int orderStatus;
            int orderDark;
            double btcAmount;
            double orderPrice;
            String date;

            for (int i = 0; i < jArray.length(); i++)
            {
                jKey = jArray.getJSONObject(i);

                orderID = jKey.getString("oid");
                orderType = jKey.getInt("type");
                btcAmount = jKey.getDouble("amount");
                orderStatus = jKey.getInt("status");
                orderPrice = jKey.getDouble("price");
                orderDark = jKey.getInt("dark");
                date = jKey.getString("date");

                GoxOrder newOrder =
                    new GoxOrder(
                        orderID,
                        orderType,
                        orderStatus,
                        orderDark,
                        btcAmount,
                        orderPrice,
                        date);

                goxAccount.addOrder(newOrder);
            }
        }
        catch (Exception e)
        {


          //fix: cant create popup in thread
            //createPopup("Getting orders was not successful.\nCheck your Wifi or 3G connection");
        }

    }

    /**
     * mOrderView run() is called when our OrderThread is finished
     */
    final Runnable mOrderView = new Runnable() {
         public void run()
         {
             safelyDismiss(orderProgressDialog);
             createPopup(goxAccount.getOrders());
         }
     };

     /////////////////////////////////////////////////////////////////////////

     /**
      * requestPlaceOrder creates a thread and dialog to place the current order
      * Call this instead of calling placeOrder directly
      */
     private void requestPlaceOrder() {
         if(placeOrderProgressDialog != null && placeOrderProgressDialog.isShowing()) {
             return;
         }
         placeOrderProgressDialog = ProgressDialog.show(this, "Working..", "Placing order", true, false);
         PlaceOrderThread pot = new PlaceOrderThread();
         pot.start();
     }

     public class PlaceOrderThread
         extends Thread
     {

         public void run()
         {
             placeOrder();
             mPlaceOrderHandler.post(mPlaceOrderView); //after retrieveOrders is done, do this
         }

     }


     /**
      * placeOrder connects to gox and places the current order
      * NOTE: call requestPlaceOrder() directly for a threaded version
      */
     private void placeOrder()
     {
         if(goxPlaceOrder == null) return;

         HttpClient httpclient = new DefaultHttpClient();
         HttpPost httppost = null;

         if(goxPlaceOrder.getOrderType() == GoxOrder.TYPE_SELL)
             httppost = new HttpPost("https://mtgox.com/code/sellBTC.php");
         else if(goxPlaceOrder.getOrderType() == GoxOrder.TYPE_BUY)
             httppost = new HttpPost("https://mtgox.com/code/buyBTC.php");
         else
         {
             createPopup("Placing your order was not successful.\nCould not determine if it was a buy or sell order");
             return;
         }

         String pName = goxAccount.getAccountName();
         String pPass = goxAccount.getAccountPass();
         goxAccount.clearOrders();

         try
         {
             List<NameValuePair> nameValuePairs =
                 new ArrayList<NameValuePair>(2);
             nameValuePairs.add(new BasicNameValuePair("name", pName));
             nameValuePairs.add(new BasicNameValuePair("pass", pPass));
             nameValuePairs.add(new BasicNameValuePair("amount", ""+goxPlaceOrder.getBtcAmount()));
             nameValuePairs.add(new BasicNameValuePair("price", ""+goxPlaceOrder.getOrderPrice()));
             httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

             goxPlaceOrder = null;

             HttpResponse response = httpclient.execute(httppost);

             InputStream is = response.getEntity().getContent();
             BufferedInputStream bis = new BufferedInputStream(is);
             ByteArrayBuffer baf = new ByteArrayBuffer(200);

             // convert byte array to string
             int current = 0;
             while ((current = bis.read()) != -1)
             {
                 baf.append((byte)current);
             }

             String text = new String(baf.toByteArray());

             //fix: cant create popup in thread
             //createPopup(text);

             JSONObject jParse = new JSONObject(text);

             JSONArray jArray = jParse.getJSONArray("orders");
             JSONObject jKey;

             if (jArray == null || jArray.length() <= 0) {
                  //fix: cant create popup in thread
                 //createPopup("Could not access the account...");
                 return;
             }

             String orderID;
             int orderType;
             int orderStatus;
             int orderDark;
             double btcAmount;
             double orderPrice;
             String date;

             for (int i = 0; i < jArray.length(); i++)
             {
                 jKey = jArray.getJSONObject(i);

                 orderID = jKey.getString("oid");
                 orderType = jKey.getInt("type");
                 btcAmount = jKey.getDouble("amount");
                 orderStatus = jKey.getInt("status");
                 orderPrice = jKey.getDouble("price");
                 orderDark = jKey.getInt("dark");
                 date = jKey.getString("date");

                 GoxOrder newOrder =
                     new GoxOrder(
                         orderID,
                         orderType,
                         orderStatus,
                         orderDark,
                         btcAmount,
                         orderPrice,
                         date);

                 goxAccount.addOrder(newOrder);
             }
         }
         catch (Exception e)
         {


           //fix: cant create popup in thread
             //createPopup("Getting orders was not successful.\nCheck your Wifi or 3G connection");
         }

     }

     /**
      * mOrderView run() is called when our OrderThread is finished
      */
     final Runnable mPlaceOrderView = new Runnable() {
          public void run()
          {
              safelyDismiss(orderProgressDialog);
              safelyDismiss(placeOrderProgressDialog);
              displayAccountPage();
              createPopup(goxAccount.getOrders()); //display orders after placing
          }
      };
     /////////////////////////////////////////////////////////////////////////

     private void viewGraph() {
         if(graphProgressDialog != null && graphProgressDialog.isShowing()) {
             return;
         }
         graphProgressDialog = ProgressDialog.show(this, "Working..", "Retrieving trades", true, false);
         GraphThread gt = new GraphThread();
         gt.start();
     }

     public class GraphThread
         extends Thread
     {

         public void run()
         {
             generatePreviousPriceGraph();
             mOrderHandler.post(mGraphView); //after retrieveOrders is done, do this
         }

     }

     /**
      * mGraphView run() is called when our GraphThread is finished
      */
     final Runnable mGraphView = new Runnable() {
          public void run()
          {
              safelyDismiss(graphProgressDialog);
              if(g_graphView != null) {

                  setMyView(g_graphView);
              } else {
                  createPopup("Unable to retrieve transactions, check your 3G or WiFi connection");
              }
          }
      };

    /**
     * generatePreviousPriceGraph prepares price graph of the last 48 hrs -It
     * connects to Mt Gox, reads the JSON, and plots a GraphView of it Todo:
     * store the Mt Gox results in SQLite so that we don't have to do a POST
     * every time we want the graph.
     *
     */
    private void generatePreviousPriceGraph()
    {
        g_graphView = null;
        HttpClient client = new DefaultHttpClient();
        HttpPost post =
            new HttpPost("https://www.mtgox.com/code/data/getTrades.php");
        try
        {
            HttpResponse response = client.execute(post);

            InputStream is = response.getEntity().getContent();
            BufferedInputStream bis = new BufferedInputStream(is);
            ByteArrayBuffer baf = new ByteArrayBuffer(20);

            // convert byte array to string
            int current = 0;
            while ((current = bis.read()) != -1)
            {
                baf.append((byte)current);
            }

            String text = new String(baf.toByteArray());

            JSONArray jArray = new JSONArray(text);

            /*
             * JSONArray jNames; JSONObject jPrice;
             */

            JSONObject jKey;

            if (jArray.length() <= 0)
                return;

            float[] values = new float[jArray.length()];

            for (int i = 0; i < jArray.length(); i++)
            {
                jKey = jArray.getJSONObject(i);
                values[i] = new Float(jKey.getDouble("price"));
            }

            /**
             * Lets count the min and max values so we can set our axis
             */

            float largest = Integer.MIN_VALUE;
            for (int i = 0; i < values.length; i++)
                if (values[i] > largest)
                    largest = values[i];

            float smallest = Integer.MAX_VALUE;
            for (int i = 0; i < values.length; i++)
                if (values[i] < smallest)
                    smallest = values[i];

            // we can uncomment this after we properly handle orientation
// changing
            // setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);

            // min, max, steps, pre string, post string, number of decimal
            // places
            String[] verlabels =
                GraphView.createLabels(smallest, largest, 5, "$", "", 4);

            String[] horlabels =
                new String[] { "48 hours ago", "24 hours ago", "Now" };
            g_graphView =
                new GraphView(this, values, "BTC over last 48 hours", // title
                    horlabels, // horizontal labels
                    verlabels, // vertical labels
                    GraphView.LINE, // type of graph
                    smallest, // min
                    largest); // max

        }
        catch (Exception e)
        {
            return;
        }

    }

    /**
     * Here we display specific info from Mt.Gox and tell the user to install
     * the Widget
     */
    public void updateStats()
    {
        HttpClient client = new DefaultHttpClient();
        HttpPost post =
            new HttpPost("https://www.mtgox.com/code/data/ticker.php");
        try
        {
            HttpResponse response = client.execute(post);

            InputStream is = response.getEntity().getContent();
            BufferedInputStream bis = new BufferedInputStream(is);
            ByteArrayBuffer baf = new ByteArrayBuffer(20);

            // convert byte array to string
            int current = 0;
            while ((current = bis.read()) != -1)
            {
                baf.append((byte)current);
            }
            String text = new String(baf.toByteArray());
            JSONObject jObject = new JSONObject(text);
            JSONObject jTicker = jObject.getJSONObject("ticker");

            /*
             * tv = (TextView)findViewById(R.id.displayText); highText =
             * (TextView)findViewById(R.id.highText); lowText =
             * (TextView)findViewById(R.id.lowText); volText =
             * (TextView)findViewById(R.id.volText); buyText =
             * (TextView)findViewById(R.id.buyText); sellText =
             * (TextView)findViewById(R.id.sellText); lastText =
             * (TextView)findViewById(R.id.lastText); highText.setText("High: "
             * + jTicker.getString("high")); lowText.setText("Low: " +
             * jTicker.getString("low")); volText.setText("Vol: " +
             * jTicker.getString("vol")); buyText.setText("Buy: " +
             * jTicker.getString("buy")); sellText.setText("Sell: " +
             * jTicker.getString("sell")); lastText.setText("Last: " +
             * jTicker.getString("last"));
             * tv.setText("Bitcoin stats retrieved from Mt Gox:\n");
             */
            endText
                .setText("\nIMPORTANT: Be sure to use the Widget!\n On the "
                    + "home screen, long press on an empty space, then select Android"
                    + " Widgets, then select Bitcoin Alert!\n\nTips: Click on the "
                    + "bitcoin in the widget to bring up this screen. The widget automatically"
                    + " refreshes every 30 minutes; the update time is displayed in red if the "
                    + "update was not successful, which is usally due to dropped 3G or Wifi signal."
                    + " Press the 'menu' key on your Android device and select 'Force Widget Refresh'"
                    + " to fix a failed update. \n\nAbout: Bitcoin Alert created by Dest Romano of "
                    + "Philosophy apps. Graphs created by the GraphView library, written by Arno Den "
                    + "Hond, modified by Dest Romano.");
        }
        catch (Exception e)
        {
            // e.printStackTrace();
            // tv.setText(getStackTrace(e));

            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder
                .setMessage("Could not retrieve stats from Mt.Gox.\n\nCheck 3G or Wifi connection and try again.");
            builder.setPositiveButton(
                "ok",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id)
                    {
                        dialog.cancel();
                    }
                });

            AlertDialog alert = builder.create();
            alert.show();
        }
    }


    /**
     * createTicker creates a notification which only briefly appears in the
     * ticker bar
     *
     * @param ctxt
     *            the context (if you don't have one, use
     *            getApplicactionContext())
     * @param icon
     *            (such as R.drawable.bitcoin)
     * @param tickerText
     *            (notification ticker)
     * @param pId
     *            the unique notifcaiton id, use different id's for multiple
     *            tickers at once
     */
    private static void createTicker(
        Context ctxt,
        int icon,
        CharSequence tickerText,
        int pId)
    {
        String ns = Context.NOTIFICATION_SERVICE;
        NotificationManager mNotificationManager =
            (NotificationManager)ctxt.getSystemService(ns);
        long when = System.currentTimeMillis();
        Notification notification = new Notification(icon, tickerText, when);

        Intent notificationIntent =
            new Intent(ctxt, WatcherWidgetProvider.class);
        PendingIntent contentIntent =
            PendingIntent.getActivity(ctxt, 0, notificationIntent, 0);

        notification.setLatestEventInfo(ctxt, null, null, contentIntent);

        mNotificationManager.notify(pId, notification);
        mNotificationManager.cancel(pId);
    }


    /**
     * createTicker creates a notification which only briefly appears in the
     * ticker bar
     *
     * @param ctxt
     *            the context (if you don't have one, use
     *            getApplicactionContext())
     * @param icon
     *            (such as R.drawable.bitcoin)
     * @param tickerText
     *            (notification ticker)
     */
    private static void createTicker(
        Context ctxt,
        int icon,
        CharSequence tickerText)
    {
        String ns = Context.NOTIFICATION_SERVICE;
        NotificationManager mNotificationManager =
            (NotificationManager)ctxt.getSystemService(ns);
        long when = System.currentTimeMillis();
        Notification notification = new Notification(icon, tickerText, when);

        Intent notificationIntent =
            new Intent(ctxt, WatcherWidgetProvider.class);
        PendingIntent contentIntent =
            PendingIntent.getActivity(ctxt, 0, notificationIntent, 0);

        notification.setLatestEventInfo(ctxt, null, null, contentIntent);

        mNotificationManager.notify(1, notification);
        mNotificationManager.cancel(1);
    }


    /**
     * createNotification creates a notifcation which stays in the notifcation
     * bar till removed
     *
     * @param Context
     *            ctxt
     * @param icon
     *            (such as R.drawable.bitcoin)
     * @param tickerText
     *            (notification ticker)
     * @param contentTitle
     *            (title of notification)
     * @param contentText
     *            (details of notification)
     */
    private static void createNotification(
        Context ctxt,
        int icon,
        CharSequence tickerText,
        CharSequence contentTitle,
        CharSequence contentText)
    {
        String ns = Context.NOTIFICATION_SERVICE;
        NotificationManager mNotificationManager =
            (NotificationManager)ctxt.getSystemService(ns);
        long when = System.currentTimeMillis();
        Notification notification = new Notification(icon, tickerText, when);

        Intent notificationIntent = new Intent(ctxt, BitcoinWatcher.class);
        PendingIntent contentIntent =
            PendingIntent.getActivity(ctxt, 0, notificationIntent, 0);

        notification.setLatestEventInfo(
            ctxt,
            contentTitle,
            contentText,
            contentIntent);

        mNotificationManager.notify(1, notification);
    }


    /**
     * this allows us to turn error traces into text so we can display them in a
     * TextView
     */
    private String getStackTrace(Exception t)
    {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw, true);
        t.printStackTrace(pw);
        pw.flush();
        sw.flush();
        return sw.toString();
    }


    private void createPopup(String pMessage)
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(pMessage);
        builder.setPositiveButton("ok", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id)
            {
                dialog.cancel();
            }
        });

        AlertDialog alert = builder.create();
        alert.show();
    }
    /*
     * called when the screen rotates or keyboard is hidden
     */
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
      super.onConfigurationChanged(newConfig);
      restoreView();
    }

    /**
     * handles the hardware back button
     */

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event)  {
       if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
            restorePreviousView();

           return true;
       }

    return super.onKeyDown(keyCode, event);
    }


    private void readPreferences() {
            // Get the xml/preferences.xml preferences
            SharedPreferences prefs = PreferenceManager
                            .getDefaultSharedPreferences(getBaseContext());

            SharedPreferences.OnSharedPreferenceChangeListener prefListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
                public void onSharedPreferenceChanged(SharedPreferences pPrefs,String key) {
                    pref_Username = pPrefs.getString("editTextPref", "");

                }
            };

            prefs.registerOnSharedPreferenceChangeListener(prefListener);

            pref_Username = prefs.getString("editTextPref", "");
    }



    /**
     * if the the back button is pressed, restore the previous view
     */
    private void restorePreviousView() {
        if(!previousViews.empty()) {
            currentView = previousViews.pop();

            restoreView();
        }
    }

    /**
     * restores the current view, for example if the screen is rotated
     */
    private void restoreView() {
        if(currentView == USE_GRAPH_VIEW) setContentView(currentGraphView);
        else setContentView(currentView);

        if(currentView == R.layout.main) {
            endText = (TextView)findViewById(R.id.endText);
            endText
                .setText("\nIMPORTANT: Be sure to use the Widget!\n On the "
                    + "home screen, long press on an empty space, then select Android"
                    + " Widgets, then select Bitcoin Alert!\n\nTips: Click on the "
                    + "bitcoin in the widget to bring up this screen. The widget automatically"
                    + " refreshes every 30 minutes; the update time is displayed in red if the "
                    + "update was not successful, which is usally due to dropped 3G or Wifi signal."
                    + " Press the 'menu' key on your Android device and select 'Force Widget Refresh'"
                    + " to fix a failed update. \n\nAbout: Bitcoin Alert created by Dest Romano of "
                    + "Philosophy apps. Graphs created by the GraphView library, written by Arno Den "
                    + "Hond, modified by Dest Romano.");

            displayMenu();
        }
        if(currentView == R.layout.account) {
            currentView = previousViews.pop();
            displayAccountPage();

        }
    }

    private void safelyDismiss(ProgressDialog dialog) {
        if(dialog != null && dialog.isShowing()) {
            dialog.dismiss();
        }
    }

}
